#include "testfunctions.h"

#include <string.h>
#include <charconv>

extern "C" {
#ifndef USE_CUSTOM_GMSSL
#include <openssl/lhash.h>
#include <openssl/bn.h>
#endif
// #include <openssl/provider.h>
}

#include "pkcs11/pkcs11test.h"
#include "pkcs11/skftest.h"
#include "pkcs11/skftest.h"

typedef struct Student_st
{
    char name[20];
    int age;
    char otherInfo[200];
}Student;

void Ascii2Hex(const std::string& hex_str,
        std::vector<uint8_t>& hex_array) {
  int len = hex_str.size() / 2;
  if(len < 0)
    return ;
  hex_array.reserve(len);
  char* str_ptr = (char *)hex_str.data();

  for(volatile int i = 0 ;i < len; i++) {
    uint8_t data;
    if( auto [p, err] = std::from_chars(str_ptr, str_ptr + 2, data, 16);
        err == std::errc() ) {
      hex_array.push_back(data);
    }
    str_ptr += 2;

  }


  // for(volatile int i = 0 ;i < len; ) {
  //   i++;
  //   uint8_t data = 0;
  //   sscanf(str_ptr, "%02x", &data);
  //   hex_array.push_back(data);
  //   str_ptr += 2;
  // }
}


static int Student_cmp(const void *a, const void *b)
{
    char *namea=((Student *)a)->name;
    char *nameb=((Student *)b)->name;
    return strcmp(namea,nameb);
}

static void PrintValue(void *data)
{
    Student* a   = (Student*) data;
    printInfo("name :%s\n",a->name);
    printInfo("age :%d\n",a->age);
    printInfo("otherInfo : %s\n",a->otherInfo);
}

static void PrintValue_arg(void *data,void *b)
{
    int flag=0;
    flag=*(int *)b;
    Student *a = (Student *)data;
    printInfo("用户输入参数为:%d\n",flag);
    printInfo("name :%s\n",a->name);
    printInfo("age :%d\n",a->age);
    printInfo("otherInfo : %s\n",a->otherInfo);
}

void TestHash() {
#ifndef USE_CUSTOM_GMSSL
    int flag=11;
    OPENSSL_LHASH *h;
    Student s1={"zcp",28,"hu bei"},
            s2={"forxy",28,"no info"},
            s3={"skp",24,"student"},
            s4={"zhao_zcp",28,"zcp's name"},
            *s5;
    void *data;
    h=OPENSSL_LH_new(NULL,Student_cmp);
    if(h==NULL)
    {
        printf("err.\n");
        return ;
    }
    data=&s1;
    lh_insert(h,data);
    data=&s2;
    lh_insert(h,data);
    data=&s3;
    lh_insert(h,data);
    data=&s4;
    lh_insert(h,data);
    /* 打印*/
    lh_doall(h,PrintValue);
    lh_doall_arg(h,PrintValue_arg,(void *)(&flag));
    data=lh_retrieve(h,(const void*)"skp");
    if(data==NULL)
    {
        printMsg("can not look up skp!\n");
        lh_free(h);
    }
    s5=(Student* )data;
    printMsg("student name : %s\n",s5->name);
    printMsg("sutdent age : %d\n",s5->age);
    printMsg("student otherinfo : %s\n",s5->otherInfo);
    lh_free(h);
#endif
}


void TestECC() {

}

void TestBigNumber() {
  #ifndef USE_CUSTOM_GMSSL
    BIGNUM	*ret1=NULL;
    char	*p=NULL;
    char	*p1=NULL;
    int		len=0;

    ret1=BN_bin2bn((const unsigned char*)"242424ab",8, NULL);
    p=BN_bn2dec(ret1);
    p1=BN_bn2hex(ret1);
    printMsg("decimal:%s, hex: %s\n",p, p1);
    BN_free(ret1);
    OPENSSL_free(p);
    OPENSSL_free(p1);
#endif
}

void ReadCert(const char* path) {

}

void TestProvider() {


}


void TestSM4()
{

}

void TestSM4GCM() {





}

void TestAES128()
{

}

void TestSM2()
{

}

void TestRSA()
{

}

void TestDSA()
{

}

void TestSM3()
{

}

void TestSha256()
{

}

void TestSSLHandshake()
{

}

void TestPKI12()
{

}

void TestPKI11(const std::string& lib_path,
               const std::string& pin) {
  if(!InitCK(lib_path)) {
    UnInitCK();
    return ;
  }

  LoginCK(pin);
}

void TestSKF(const std::string &lib_path,
             const std::string &pin) {
    if(InitSDF(lib_path))
        UnInitSDF();
}
